package com.miaosha.ms_05.service;

import com.miaosha.ms_05.SystemConstant;
import com.miaosha.ms_05.dao.MiaoshaGoodsDao;
import com.miaosha.ms_05.dao.MiaoshaOrderDao;
import com.miaosha.ms_05.domain.*;
import com.miaosha.ms_05.exception.GlobalException;
import com.miaosha.ms_05.prefix.*;
import com.miaosha.ms_05.redis.JedisService;
import com.miaosha.ms_05.result.CodeMsg;
import com.miaosha.ms_05.vo.GoodsVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * @Description //TODO
 * @Author Administrator
 * @DATE 2020/9/19 21:22
 **/
@Service
public class MiaoshaService {

    private Logger logger = LoggerFactory.getLogger(MiaoshaService.class);

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsService goodsService;

    @Resource
    private MiaoshaOrderDao miaoshaOrderDao;

    @Resource
    private MiaoshaGoodsDao miaoshaGoodsDao;

    @Resource
    private JedisService jedisService;

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public OrderInfo buyGoods(GoodsVo goods, User user) {
        if (user == null) {
            throw new GlobalException(CodeMsg.USER_EMPTY);
        }
        Long userId = user.getId();
        Long goodsId = goods.getId();
        if (goodsId == null) {
            throw new GlobalException(CodeMsg.GOOD_ID_EMPTY);
        }
        //校验是否该用户已经秒杀过该商品
        boolean miaoshaOrderExist = this.checkUserIdAndGoodsIdExistsFromRedis(userId, goodsId);
        if (miaoshaOrderExist) {
            throw new GlobalException(CodeMsg.ORDER_REPEAT);
        }
        //获取商品详情
        String goodsName = goods.getGoodsName();
        //1.减去商品库存
        //Redis 预减
        boolean descFlag = this.descMiaoshaGoodsStockFromRedis(goodsId);
        if(!descFlag){
            throw new GlobalException(CodeMsg.STOCK_NOT_ENOUGH);
        }
        //1.1.1 修改活动商品库存(DB)
        Integer count = miaoshaGoodsDao.updateStock(goodsId);
        if (count < 1) {
            throw new GlobalException(CodeMsg.STOCK_NOT_ENOUGH);
        }
        // 1.1 修改活动商品库存(Redis)
        jedisService.incr(MiaoshaGoodsKey.MIAOSHA_GOODS_ID_COUNT, goodsId.toString());

        //1.2.1 修改商品库存(DB)
        System.out.println("商品库存:" + goods.getGoodsStock());
        goodsService.updateStock(goods);
        logger.info("成功减去库存，商品ID ={}", goodsId);
        //1.2.2 删除缓存中商品信息，并重新赋值(Redis)
        goods.setStockCount(goods.getGoodsStock()-1);
        jedisService.deleteByKeyPrefixAndKey(GoodsKey.GOODS_KEY, goodsId.toString());
        jedisService.set(GoodsKey.GOODS_KEY, goods.getId().toString(), goods, GoodsVo.class);

        //2.1 生成订单(DB)
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateDate(new Date());
        orderInfo.setDeliveryAddrId(1L);
        orderInfo.setGoodsCount(1);
        orderInfo.setGoodsId(goodsId);
        orderInfo.setGoodsName(goodsName);
        orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
        orderInfo.setOrderChannel(SystemConstant.OrderChannel.PC.getCode());
        orderInfo.setUserId(userId);
        orderInfo.setStatus(SystemConstant.OrderStatusEnum.NEW.getCode());
        orderService.insert(orderInfo);
        //2.2 生成订单（Redis）
        orderService.putToRedis(orderInfo);
        logger.info("----成功生成订单信息 订单ID={}", orderInfo.getId());

        //3.1 生成秒杀订单(DB)
        MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
        miaoshaOrder.setGoodsId(goodsId);
        miaoshaOrder.setOrderId(orderInfo.getId());
        miaoshaOrder.setUserId(userId);

        miaoshaOrderDao.insert(miaoshaOrder);
        //3.2 插入订单相关信息（Redis）
        this.putMiaoshaOrderToRedis(miaoshaOrder);
        logger.info("----成功生成秒杀订单信息 秒杀订单ID={}", miaoshaOrder.getId());
        return orderInfo;
    }

    public static void main(String[] args) {
        int num = new Random(1).nextInt(100);
        System.out.println(num);

    }

    public void rest() {
        //恢复商品库存
        goodsService.resetStock();
        //恢复抢购库存
        miaoshaGoodsDao.resetStock();
        //删除秒杀订单
        miaoshaOrderDao.deleteMiaoshaOrder();
        //删除订单
        orderService.delete();
        //删除缓存中相关商品信息
        this.deleteGoodsInfoFromRedis();
        //删除缓存中相关订单信息
        this.deleteOrderInfoFromRedis();
        //重新放入商品相关信息到 缓存中
        putGoodsInfoToRedis();
    }

    /**
     * @return void
     * @Description 将商品相关信息放入 redis 中
     **/
    public void putGoodsInfoToRedis() {
        //1. 商品信息
        List<GoodsVo> goodsList = goodsService.listGoodsVo();
        for (GoodsVo goodsVo : goodsList) {
            jedisService.set(GoodsKey.GOODS_KEY, goodsVo.getId().toString(), goodsVo, GoodsVo.class);
        }
        //2. 商品ID + 库存
        List<MiaoshaGoods> miaoshaGoodsList = miaoshaGoodsDao.findGoodsIdAndStockCount();
        for (MiaoshaGoods miaoshaGoods : miaoshaGoodsList) {
            jedisService.set(MiaoshaGoodsKey.MIAOSHA_GOODS_ID_COUNT, miaoshaGoods.getGoodsId().toString(), miaoshaGoods.getStockCount(), Integer.class);
        }
    }

    /**
     * @return void
     * @Description 从 redis 中删除 商品相关信息
     **/
    public void deleteGoodsInfoFromRedis() {
        //1. 删除商品相关信息
        jedisService.deleteByKeyPrefix(GoodsKey.GOODS_KEY);
        //2. 删除秒杀商品相关信息
        jedisService.deleteByKeyPrefix(MiaoshaGoodsKey.MIAOSHA_GOODS_ID_COUNT);
    }

    public void deleteOrderInfoFromRedis() {
        //1.删除订单相关信息
        jedisService.deleteByKeyPrefix(OrderKey.ORDER_KEY);
        //2.删除活动订单相关信息
        jedisService.deleteByKeyPrefix(MiaoshaOrderKey.MIAOSHA_ORDER_KEY);
        //3.删除用户ID + 商品ID
        jedisService.deleteByKeyPrefix(MiaoshaOrderKey.USERID_AND_GOODSID);
    }

    /**
     * @param goodsId
     * @return com.miaosha.ms_05.vo.GoodsVo
     * @Description 根据商品ID从缓存中 获取商品对象
     **/
    public GoodsVo getGoodsVoByIdFromRedis(Long goodsId) {
        if (goodsId == null) {
            return null;
        }
        return jedisService.get(GoodsKey.GOODS_KEY, goodsId.toString(), GoodsVo.class);
    }
    /**
     * @Description 根据用户Id 和 商品ID 判断是否已有秒杀订单
     * @param userId
     * @param goodsId
     * @return boolean
     **/
    public boolean checkUserIdAndGoodsIdExistsFromRedis(Long userId,Long goodsId){
        String key = userId.toString().concat("-").concat(goodsId.toString());
        return jedisService.exists(MiaoshaOrderKey.USERID_AND_GOODSID,key);
    }

    public void putMiaoshaOrderToRedis(MiaoshaOrder miaoshaOrder){
        //秒杀订单
//        jedisService.set(MiaoshaOrderKey.MIAOSHA_ORDER_KEY,miaoshaOrder.getId().toString(),miaoshaOrder,MiaoshaOrder.class);
        //秒杀用户ID-商品ID
        Long goodsId = miaoshaOrder.getGoodsId();
        Long userId = miaoshaOrder.getUserId();
        String key = userId.toString().concat("-").concat(goodsId.toString());
        jedisService.set(MiaoshaOrderKey.USERID_AND_GOODSID,key,key,String.class);
    }

    /**
     * @Description 从Redis 预减 活动商品库存
     * @param goodsId
     * @return java.lang.Integer
     **/
    public boolean descMiaoshaGoodsStockFromRedis(Long goodsId){
        Integer count = jedisService.get(MiaoshaGoodsKey.MIAOSHA_GOODS_ID_COUNT, goodsId.toString(),Integer.class);
        if(count < 1){
            return  false;
        }
        jedisService.desc(MiaoshaGoodsKey.MIAOSHA_GOODS_ID_COUNT, goodsId.toString());
        return  true;
    }
}
